iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
1
自我挑戰組

網頁前端框架 Vue 3 從頭開始(重新挑戰)系列 第 18

vue3 Composition API 學習手冊-18 組件emit的用法

  • 分享至 

  • xImage
  •  

上一篇文章我們提到Components可以接收父層傳遞過來的參數進行處理,這次我們首先就來看看子層通知父層的方法。

利用上一篇文章的最後一個範例來進行說明,當時我們使用兩個按鈕上面各有紀錄一個數量,透過使用者的點選讓該產品的數量開始遞減,用來解釋每個組件有自己獨立的Data,回憶完這個範例之後,我們期望對這個範例進行強化,除了原先的功能之外,我們希望可以在上面加一個數量累計的功能,當使用者點選按鈕的時候,去計算一個加總的數字,而總數這個Data應該就是隸屬於Parent內的,所以我們希望由子層來通知父層來更新這個數據。

emit


為了完成這樣的範例,我們必須使用組件中的emit來完成,先來看看程式碼的部分:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@next"></script>
    <style>
        button {
            padding: 10px;
        }

        h2 {
            font-size: 18px;
            font-family: "微軟正黑體";
        }
        
    </style>
</head>

<body>
    <div id="app">
        <h2>Order quantity : {{ state.total }}</h2>
        <vuebutton title="iPhone" :start="5" @vuebutton-click="countTotal"></vuebutton>
        <vuebutton title="iPad" :start="10" @vuebutton-click="countTotal"></vuebutton>
    </div>
</body>

</html>

<script>
const { reactive } = Vue;
const app = {
    setup(){
        const state = reactive({
            total: 0,
        })
        function countTotal(){
            state.total ++;
        }
        return { state, countTotal }
    }
}
const myVue = Vue.createApp(app);

myVue.component("vuebutton", {
    props: {
        title: {
            type: String,
            required: true,
        },
        start: {
            type: Number,
            default: 0,
        },
    },
    template: `<button @click="minus">{{ state.title }} 庫存 {{ state.start }} 件</button>`,
    setup(props, target){
        const state = reactive({
            title: props.title,
            start: props.start,
        })
        function minus(){
            if (state.start <= 0) {
                state.start = 0;
            } else {
                state.start--;
                target.emit("vuebutton-click");
            }
        }
        return{ state, minus }
    },
})
myVue.mount("#app");
</script>

範例檔

上面案例的做法最終目的要達成的就像前面所說的,期望當按鈕按下之後,父層的total可以自動加1,而做法上除了在父層加上total這個data之外,還讓子層透過emit去“發射”一個事件出來,事件的名稱是vuebutton-click,當事件發射後,可以看到在父層使用v-on(簡寫成@)去監聽這個事件,當事情發生時會讓total+1。

注意第59行的setup中我們帶入了第二個參數target,在這邊就是我們的上層對象,但如果你認為以上的做法何必這麼麻煩,直接在vuebutton上面監聽click事件不就好了?

<vuebutton title="iPhone" :start="5" @click="state.total++"></vuebutton>

這樣的觀念就有點不正確了,因為這樣會讓total無條件+1,包含庫存數量已經歸0之後再按下這個按鈕,total的數量還是會不斷增加,也就是父層和子層的邏輯就被獨立開來了,這樣的做法沒辦法達到我們期望的效果。

從上面的範例我們可以得到結論:

  • 父層透過props來傳遞給子層
  • 子層透過emit來傳遞事件給父層


上一篇
vue3 Composition API 學習手冊-17 組件的資料和函數
下一篇
vue3 Composition API 學習手冊-19 組件的綜合練習
系列文
網頁前端框架 Vue 3 從頭開始(重新挑戰)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言